package main

import (
	"bytes"
	"encoding/json"
	"github.com/astaxie/beego/logs"
	"io"
	"net"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"time"
)

var (
	log     *logs.BeeLogger
	ExecDir string
	Spath   = "/var/run/guard/guard.sock"
)

func sendHeartbeat() {
	pk := map[string]interface{}{"type": "2"}
	msg, _ := json.Marshal(pk)
	for {
		tcpAddr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:9999")
		conn, err := net.DialTCP("tcp", nil, tcpAddr)
		if err != nil {
			log.Error("connect to client faild , Ready to restart")
			cmd := exec.Command("bash", "-c", "./clientd.sh restart")
			err := cmd.Run()
			if nil != err {
				log.Error("restart faild, five seconds after retry %v", err)
			}
			time.Sleep(30 * time.Second)
			continue
		}
		for {
			err := SendData(conn, msg)
			if err != nil {
				break
			}
			time.Sleep(10 * time.Second)
		}

	}
}

//读取网络数据

func ReadData(conn net.Conn) []byte {
	var data bytes.Buffer
	var buf [1024]byte
	for {
		n, err := conn.Read(buf[0:])
		if err != nil {
			if err == io.EOF {
				log.Info("recv done")
				//fmt.Println("recv error:" + err.Error())
				break
			} else {
				log.Warn("recv data error <%v>", err)
				return nil
			}
		}
		if buf[n-1] == '\n' {
			data.Write(buf[0 : n-1])
			break
		} else {
			data.Write(buf[0:n])
		}

	}
	return data.Bytes()

}

//发送网络数据
func SendData(conn net.Conn, data []byte) error {
	data = append(data, '\n')
	_, err := conn.Write(data)
	if err != nil {
		//fmt.Println("send error" + err.Error())
		return err
	}
	return nil
}
func init() {
	log = logs.NewLogger(100)
	os.MkdirAll("./logs", 0755)
	os.MkdirAll("/var/run/guard", 0755)
	log.SetLogger("console", "")
	log.EnableFuncCallDepth(true)
	log.SetLogger("file", `{"filename":"./logs/guard.log","rotate":true,"maxdays":7}`)
	pth, _ := exec.LookPath(os.Args[0])
	ExecDir = filepath.Dir(pth)
	fd, err := os.Create("/var/run/guard/guard.pid")
	if err != nil {
		log.Error("create pid file error <%v> ", err)
		return
	}
	defer fd.Close()
	fd.WriteString(strconv.Itoa(os.Getpid()))
}

func startListen() {
	l, err := net.Listen("unix", Spath)
	if err != nil {
		log.Error("start listen error > %v", err)
		os.Exit(1)
	}
	defer l.Close()
	for {
		conn, err := l.Accept()
		if err != nil {
			log.Error("accept error > %v", err)
			continue
		}
		defer conn.Close()
		for {
			msg := ReadData(conn)
			if len(msg) == 0 {
				break
			}
			var pack map[string]interface{}
			data := strings.TrimSpace(string(msg))
			if !strings.Contains(data, "type") {
				continue
			}
			if err := json.Unmarshal([]byte(data), &pack); err != nil {
				break
			}
			switch pack["type"] {
			case "2":
				log.Info("receive a heartbeat packet from %s", conn.RemoteAddr().String())
			default:
				continue
			}
		}
	}
}

func main() {
	go sendHeartbeat()
	startListen()
}
